package main

import (
	"fmt"
	"strings"
)

//基本介绍：闭包就是一个函数和与其相关的引用环境组合的一个整体（实体）
//累加器
func AddUpper() func(int) int {
	var n int = 10
	return func(x int) int {
		n = n + x
		return n
	}
}

/*
1编写一个函数makeSuffix(suffix string)可以接收一个文件后缀名(比如.jpg)，并返回一个闭包
2调用闭包，可以传入一个文件名，如果该文件名没有指定的后缀(比如.jpg)，则返回文件名.jpg，如果已经有.jpg后缀，则返回原文件名
3要求使用闭包的方式完成
4strings.HasSuffix，该函数可以判断某个字符串是否有指定的后缀
*/
//返回的匿名函数和makeSuffix(suffix string)的suffix变量组合成一个闭包，因为返回的函数引用到suffix这个变量
//闭包的好处，如果使用传统的方法，也可以轻松完成这个功能，但是传统方法需要每次都传入后缀名，比如.jpg，而闭包因为可以保留上次引用的某个值，所以我们传入一次就可以反复使用
func makeSuffix(suffix string) func(string) string {
	return func(name string) string {
		//如果name没有指定后缀，则加上，否则就返回原来的名字
		if !strings.HasSuffix(name, suffix) {
			return name + suffix
		}
		return name
	}
}

//AddUpper是一个函数，返回的数据类型是func(int) int
//闭包的说明：返回的是一个匿名函数，但是这个匿名函数引用到函数外的n，因此这个匿名函数就和n形成一个整体，构成闭包
//可以这样理解：闭包是类，函数是操作，n是字段，函数和它使用到的n构成闭包
//当我们反复的调用f函数时，因为n是初始化一次，因此每调用一次就进行累计
//要搞清楚闭包的关键，就是要分析出返回的它使用(引用)到哪些变量，因为函数和它引用到的变量共同构成闭包
func main() {
	f := AddUpper()
	fmt.Println(f(1)) //11
	fmt.Println(f(2)) //13

	//测试makeSuffix的使用
	//返回一个闭包
	f2 := makeSuffix(".jpg")
	fmt.Println("文件名处理后=", f2("winter"))   //winter.jpg
	fmt.Println("文件名处理后=", f2("bird.jpg")) //bird.jpg
}
